package cn.iocoder.yudao.module.wine.job;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.wine.controller.app.supplyinfo.enums.SupplyInfoEnum;
import cn.iocoder.yudao.module.wine.controller.app.supplymarket.enums.SupplyMarketEnum;
import cn.iocoder.yudao.module.wine.dal.dataobject.countnameconfig.CountNameConfigDO;
import cn.iocoder.yudao.module.wine.dal.dataobject.supplyinfo.SupplyInfoDO;
import cn.iocoder.yudao.module.wine.dal.dataobject.supplymarket.SupplyMarketDO;
import cn.iocoder.yudao.module.wine.dal.mysql.countnameconfig.CountNameConfigMapper;
import cn.iocoder.yudao.module.wine.dal.mysql.supplyinfo.SupplyInfoMapper;
import cn.iocoder.yudao.module.wine.dal.mysql.supplymarket.SupplyMarketMapper;
import cn.iocoder.yudao.module.wine.dal.mysql.supplytype.SupplyTypeMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zyc
 * @createDate 2024/6/7 10:31
 */
@Component
@Slf4j
public class SupplyMarketJob implements JobHandler {

    @Resource
    private SupplyInfoMapper supplyInfoMapper;

    @Resource
    private SupplyTypeMapper supplyTypeMapper;

    @Resource
    private SupplyMarketMapper supplyMarketMapper;

    @Resource
    private CountNameConfigMapper countNameConfigMapper;

    @Resource
    private DictDataApi dataApi;

    @Override
    @TenantIgnore
    public String execute(String param) throws Exception {
        log.info("定时任务开始!");
        List<CountNameConfigDO> countNameConfigDOS = countNameConfigMapper.selectList();
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime yesterday = now.minusDays(1);

        //所有的供求数据
        List<SupplyInfoDO> allDataList = supplyInfoMapper.selectList(new LambdaQueryWrapperX<SupplyInfoDO>()
                .between(SupplyInfoDO::getUpdateTime, yesterday, now)
                .eq(SupplyInfoDO::getStatus, SupplyInfoEnum.AUDIT.getCode())
                .eq(SupplyInfoDO::getIsCount, 1)
        );
        List<SupplyInfoDO> infoDOS = new ArrayList<>();
        countNameConfigDOS.forEach(item -> {
            Integer packing = item.getPacking(); //JACKCHEN
            Integer showYear = item.getShowYear();
            String countName = item.getCountName();
            String failoverName = item.getFailoverName();
            String name = countName + "," + failoverName;
            String[] strings = name.split(",");

            //1...

            //所有
            //根据配置获取的供求数据
            List<SupplyInfoDO> countList = supplyInfoMapper.selectList(new LambdaQueryWrapperX<SupplyInfoDO>()
                    .in(SupplyInfoDO::getCountName, strings)
                    .eq(SupplyInfoDO::getFragranceType, item.getFragranceType())
                    .eq(SupplyInfoDO::getShowYear, item.getShowYear())
                    .eq(SupplyInfoDO::getPacking, item.getPacking())
                    .eq(SupplyInfoDO::getSupplyTypeId, item.getSupplyTypeId())
                    .eq(SupplyInfoDO::getStatus, SupplyInfoEnum.AUDIT.getCode())
                    .eq(SupplyInfoDO::getIsCount, 1)
                    .between(SupplyInfoDO::getUpdateTime, yesterday, now)
            );
            if (CollectionUtil.isEmpty(countList)) {

            } else {
                infoDOS.addAll(countList);
                List<SupplyInfoDO> infoDOS1 = countList.stream().filter(data -> data.getInfoType() == 1).collect(Collectors.toList());
                List<SupplyInfoDO> infoDOS2 = countList.stream().filter(data -> data.getInfoType() == 2).collect(Collectors.toList());
                List<SupplyMarketDO> supplyMarketDOS = supplyMarketMapper.selectList(new LambdaQueryWrapperX<SupplyMarketDO>()
                        .eq(SupplyMarketDO::getInfoType, SupplyMarketEnum.MARKET.getCode())
                        .eq(SupplyMarketDO::getInfoNme, countName)
                        .eq(SupplyMarketDO::getPacking, packing)
                        .eq(SupplyMarketDO::getShowYear, showYear)
                        .orderByDesc(SupplyMarketDO::getCountTime));
                SupplyMarketDO supplyMarketDO = new SupplyMarketDO();
                supplyMarketDO.setInfoType(SupplyMarketEnum.MARKET.getCode());
                supplyMarketDO.setCountTime(LocalDateTime.now());
                supplyMarketDO.setInfoTitle(countName);
                supplyMarketDO.setInfoNme(countName);
                supplyMarketDO.setShowYear(item.getShowYear());
                supplyMarketDO.setFragranceType(item.getFragranceType());
                supplyMarketDO.setSupplyTypeId(item.getSupplyTypeId());
                supplyMarketDO.setPacking(item.getPacking());

                BigDecimal averagePrice = BigDecimal.ZERO;
                int i = 0;
                if (!CollectionUtil.isEmpty(infoDOS1)) {
                    BigDecimal price = infoDOS1.stream().map(SupplyInfoDO::getSalePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                    averagePrice = averagePrice.add(price.divide(new BigDecimal(infoDOS1.size()), 3, RoundingMode.HALF_UP));
                    i += 1;
                }
                if (!CollectionUtil.isEmpty(infoDOS2)) {
                    BigDecimal price = infoDOS2.stream().map(SupplyInfoDO::getSalePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                    averagePrice = averagePrice.add(price.divide(new BigDecimal(infoDOS2.size()), 3, RoundingMode.HALF_UP));
                    i += 1;
                }
                averagePrice = averagePrice.divide(new BigDecimal(i), 2, RoundingMode.HALF_UP);
                supplyMarketDO.setAveragePrice(averagePrice);
                if (CollectionUtil.isEmpty(supplyMarketDOS)) {
                    supplyMarketDO.setSalePrice(BigDecimal.ZERO);
                    supplyMarketDO.setStatus(SupplyMarketEnum.UNCHANGED_PRICE.getCode());
                } else {
                    BigDecimal bigDecimal = supplyMarketDOS.get(0).getAveragePrice();
                    log.info("看看上一条信息的价格: {}", bigDecimal);
                    log.info("看看本次计算的价格: {}", averagePrice);
                    if (averagePrice.compareTo(bigDecimal) > 0) {
                        //涨价
                        supplyMarketDO.setStatus(SupplyMarketEnum.RISE_IN_PRICE.getCode());
                        supplyMarketDO.setSalePrice(averagePrice.subtract(bigDecimal));
                    }
                    if (averagePrice.compareTo(bigDecimal) == 0) {
                        //未涨
//                        supplyMarketDO.setSalePrice(BigDecimal.ZERO);
                        supplyMarketDO.setSalePrice(supplyMarketDOS.get(0).getSalePrice());
                        supplyMarketDO.setStatus(SupplyMarketEnum.UNCHANGED_PRICE.getCode());
                    }
                    if (averagePrice.compareTo(bigDecimal) < 0) {
                        //降价
                        supplyMarketDO.setStatus(SupplyMarketEnum.DEPRECIATE.getCode());
                        supplyMarketDO.setSalePrice(bigDecimal.subtract(averagePrice).negate());
                    }
                }
                //2...
                supplyMarketMapper.insert(supplyMarketDO);
            }
        });


        //过滤掉配置中的供求数据
        List<SupplyInfoDO> filter = allDataList.stream()
                .filter(data -> !infoDOS.contains(data))
                .collect(Collectors.toList());

        //对供求信息进行分组
        Map<Key, List<SupplyInfoDO>> groupedObjects = new HashMap<>();
        for (SupplyInfoDO obj : filter) {
            Key key = new Key(obj.getShowYear(), obj.getPacking(), obj.getFragranceType(), obj.getSupplyTypeId());
            groupedObjects.computeIfAbsent(key, k -> new ArrayList<>()).add(obj);
        }
        if (CollectionUtil.isEmpty(groupedObjects)) {

        } else {
            for (Map.Entry<Key, List<SupplyInfoDO>> entry : groupedObjects.entrySet()) {
                List<SupplyInfoDO> value = entry.getValue();
                if (CollectionUtil.isEmpty(value)) {
                } else {
                    List<SupplyInfoDO> infoDOS1 = value.stream().filter(data -> data.getInfoType() == 1).collect(Collectors.toList());
                    List<SupplyInfoDO> infoDOS2 = value.stream().filter(data -> data.getInfoType() == 2).collect(Collectors.toList());
                    List<SupplyMarketDO> supplyMarketDOS = supplyMarketMapper.selectList(new LambdaQueryWrapperX<SupplyMarketDO>()
                            .eq(SupplyMarketDO::getInfoType, SupplyMarketEnum.MARKET.getCode())
                            .eq(SupplyMarketDO::getSupplyTypeId, entry.getKey().getD())
                            .eq(SupplyMarketDO::getFragranceType, entry.getKey().getC())
                            .eq(SupplyMarketDO::getPacking, entry.getKey().getB())
                            .eq(SupplyMarketDO::getShowYear, entry.getKey().getA())
                            .orderByDesc(SupplyMarketDO::getCountTime));
                    SupplyMarketDO supplyMarketDO = new SupplyMarketDO();
                    supplyMarketDO.setInfoType(SupplyMarketEnum.MARKET.getCode());
                    supplyMarketDO.setCountTime(LocalDateTime.now());
                    supplyMarketDO.setFragranceType(entry.getKey().getC());
                    supplyMarketDO.setSupplyTypeId(entry.getKey().getD());
                    supplyMarketDO.setInfoNme(value.get(0).getInfoName());
                    supplyMarketDO.setInfoTitle(value.get(0).getInfoTitle());
                    supplyMarketDO.setShowYear(entry.getKey().getA());
                    supplyMarketDO.setPacking(entry.getKey().getB());

                    BigDecimal averagePrice = BigDecimal.ZERO;
                    int i = 0;
                    if (!CollectionUtil.isEmpty(infoDOS1)) {
                        BigDecimal price = infoDOS1.stream().map(SupplyInfoDO::getSalePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                        averagePrice = averagePrice.add(price.divide(new BigDecimal(infoDOS1.size()), 3, RoundingMode.HALF_UP));
                        i += 1;
                    }
                    if (!CollectionUtil.isEmpty(infoDOS2)) {
                        BigDecimal price = infoDOS2.stream().map(SupplyInfoDO::getSalePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                        averagePrice = averagePrice.add(price.divide(new BigDecimal(infoDOS2.size()), 3, RoundingMode.HALF_UP));
                        i += 1;
                    }

//                    supplyMarketDO.setAveragePrice(averagePrice.divide(new BigDecimal(2), 3, RoundingMode.HALF_UP));
//                    BigDecimal price = value.stream().map(SupplyInfoDO::getSalePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
//                    BigDecimal averagePrice = price.divide(new BigDecimal(value.size()), 3, RoundingMode.HALF_UP);
                    averagePrice = averagePrice.divide(new BigDecimal(i), 2, RoundingMode.HALF_UP);
                    supplyMarketDO.setAveragePrice(averagePrice);
                    if (CollectionUtil.isEmpty(supplyMarketDOS)) {
                        supplyMarketDO.setSalePrice(BigDecimal.ZERO);
                        supplyMarketDO.setStatus(SupplyMarketEnum.UNCHANGED_PRICE.getCode());
                    } else {
                        BigDecimal bigDecimal = supplyMarketDOS.get(0).getAveragePrice();
                        log.info("看看本次计算的价格: {}", averagePrice);
                        log.info("看看上一条信息的价格: {}", bigDecimal);
                        if (averagePrice.compareTo(bigDecimal) > 0) {
                            //涨价
                            supplyMarketDO.setStatus(SupplyMarketEnum.RISE_IN_PRICE.getCode());
                            supplyMarketDO.setSalePrice(averagePrice.subtract(bigDecimal));
                        }
                        if (averagePrice.compareTo(bigDecimal) == 0) {
                            //未涨
//                            supplyMarketDO.setSalePrice(BigDecimal.ZERO);
                            supplyMarketDO.setSalePrice(supplyMarketDOS.get(0).getSalePrice());
                            supplyMarketDO.setStatus(SupplyMarketEnum.UNCHANGED_PRICE.getCode());
                        }
                        if (averagePrice.compareTo(bigDecimal) < 0) {
                            //降价
                            supplyMarketDO.setStatus(SupplyMarketEnum.DEPRECIATE.getCode());
                            supplyMarketDO.setSalePrice(bigDecimal.subtract(averagePrice).negate());
                        }
                    }
                    supplyMarketMapper.insert(supplyMarketDO);
                }


            }

            log.info("定时任务结束!");
        }
        return "定时任务执行完成";

    }


    public void temp() {
        //1...
//            //求购
//            Integer askToBuyCode = SupplyInfoEnum.ASK_TO_BUY.getCode();
//            List<SupplyInfoDO> supplyInfoDOS = supplyInfoMapper.selectList(new LambdaQueryWrapperX<SupplyInfoDO>()
//                            .eqIfPresent(SupplyInfoDO::getInfoType, askToBuyCode)
//                            .in(SupplyInfoDO::getCountName, strings));
//
//            List<SupplyMarketDO> data = supplyMarketMapper.selectList(new LambdaQueryWrapperX<SupplyMarketDO>()
//                    .eq(SupplyMarketDO::getInfoType, SupplyMarketEnum.MARKET.getCode())
//                    .eq(SupplyMarketDO::getInfoTitle, countName)
//                    .orderByDesc(SupplyMarketDO::getCountTime));
//            if (CollectionUtil.isEmpty(supplyInfoDOS)) {
//            } else {
//                SupplyMarketDO supplyMarketDO = new SupplyMarketDO();
//                supplyMarketDO.setInfoTitle(countName);
//                supplyMarketDO.setInfoNme(countName);
//                supplyMarketDO.setInfoType(SupplyMarketEnum.MARKET.getCode());
//                supplyMarketDO.setCountTime(LocalDateTime.now());
//                supplyMarketDO.setFragranceType(supplyInfoDOS.get(0).getFragranceType());
//                supplyMarketDO.setPublicationType(askToBuyCode);
////                supplyMarketDO.setShowYear();
//                supplyMarketDO.setSupplyTypeId(supplyInfoDOS.get(0).getSupplyTypeId());
//                BigDecimal price = supplyInfoDOS.stream().map(SupplyInfoDO::getSalePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
//                BigDecimal averagePrice = price.divide(new BigDecimal(supplyInfoDOS.size()), 3, RoundingMode.HALF_UP);
//                supplyMarketDO.setAveragePrice(averagePrice);
//                if (CollectionUtil.isEmpty(data)) {
//                    supplyMarketDO.setSalePrice(BigDecimal.ZERO);
//                    supplyMarketDO.setStatus(SupplyMarketEnum.UNCHANGED_PRICE.getCode());
//                } else {
//                    BigDecimal bigDecimal = data.get(0).getAveragePrice();
//                    if (averagePrice.compareTo(bigDecimal) > 0) {
//                        //涨价
//                        supplyMarketDO.setStatus(SupplyMarketEnum.RISE_IN_PRICE.getCode());
//                        supplyMarketDO.setSalePrice(averagePrice.subtract(bigDecimal));
//                    }
//                    if (averagePrice.compareTo(bigDecimal) == 0) {
//                        //未涨
//                        supplyMarketDO.setSalePrice(BigDecimal.ZERO);
//                        supplyMarketDO.setStatus(SupplyMarketEnum.UNCHANGED_PRICE.getCode());
//                    }
//                    if (averagePrice.compareTo(bigDecimal) < 0) {
//                        //降价
//                        supplyMarketDO.setStatus(SupplyMarketEnum.DEPRECIATE.getCode());
//                        supplyMarketDO.setSalePrice(bigDecimal.subtract(averagePrice));
//                    }
//                }
//                supplyMarketMapper.insert(supplyMarketDO);
//            }
//
//
//            //出售
//            Integer sellCode = SupplyInfoEnum.SELL.getCode();
//            List<SupplyInfoDO> infoDOS = supplyInfoMapper.selectList(new LambdaQueryWrapperX<SupplyInfoDO>()
//                    .eqIfPresent(SupplyInfoDO::getInfoType, askToBuyCode)
//                    .in(SupplyInfoDO::getCountName, strings));
//            if (CollectionUtil.isEmpty(infoDOS)) {
//
//            } else {
//                List<SupplyMarketDO> supplyMarketDOS = supplyMarketMapper.selectList(new LambdaQueryWrapperX<SupplyMarketDO>()
//                        .eq(SupplyMarketDO::getInfoType, SupplyMarketEnum.MARKET.getCode())
//                        .eq(SupplyMarketDO::getInfoTitle, countName)
//                        .orderByDesc(SupplyMarketDO::getCountTime));
//                SupplyMarketDO supplyMarketDO = new SupplyMarketDO();
//                supplyMarketDO.setInfoType(SupplyMarketEnum.MARKET.getCode());
//                supplyMarketDO.setCountTime(LocalDateTime.now());
//                supplyMarketDO.setInfoTitle(countName);
//                supplyMarketDO.setInfoNme(countName);
////                supplyMarketDO.setShowYear();
//                supplyMarketDO.setFragranceType(infoDOS.get(0).getFragranceType());
//                supplyMarketDO.setPublicationType(sellCode);
//                supplyMarketDO.setSupplyTypeId(infoDOS.get(0).getSupplyTypeId());
//                BigDecimal price = infoDOS.stream().map(SupplyInfoDO::getSalePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
//                BigDecimal averagePrice = price.divide(new BigDecimal(infoDOS.size()), 3, RoundingMode.HALF_UP);
//                supplyMarketDO.setAveragePrice(averagePrice);
//                if (CollectionUtil.isEmpty(supplyMarketDOS)) {
//                    supplyMarketDO.setSalePrice(BigDecimal.ZERO);
//                    supplyMarketDO.setStatus(SupplyMarketEnum.UNCHANGED_PRICE.getCode());
//                } else {
//                    BigDecimal bigDecimal = supplyMarketDOS.get(0).getAveragePrice();
//                    if (averagePrice.compareTo(bigDecimal) > 0) {
//                        //涨价
//                        supplyMarketDO.setStatus(SupplyMarketEnum.RISE_IN_PRICE.getCode());
//                        supplyMarketDO.setSalePrice(averagePrice.subtract(bigDecimal));
//                    }
//                    if (averagePrice.compareTo(bigDecimal) == 0) {
//                        //未涨
//                        supplyMarketDO.setSalePrice(BigDecimal.ZERO);
//                        supplyMarketDO.setStatus(SupplyMarketEnum.UNCHANGED_PRICE.getCode());
//                    }
//                    if (averagePrice.compareTo(bigDecimal) < 0) {
//                        //降价
//                        supplyMarketDO.setStatus(SupplyMarketEnum.DEPRECIATE.getCode());
//                        supplyMarketDO.setSalePrice(bigDecimal.subtract(averagePrice));
//                    }
//                }
//                supplyMarketMapper.insert(supplyMarketDO);
//
//            }

        //2....

//                BigDecimal price = countList.stream().map(SupplyInfoDO::getSalePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
//                BigDecimal averagePrice = price.divide(new BigDecimal(countList.size()), 3, RoundingMode.HALF_UP);
//                supplyMarketDO.setAveragePrice(averagePrice);
//                if (CollectionUtil.isEmpty(supplyMarketDOS)) {
//                    supplyMarketDO.setSalePrice(BigDecimal.ZERO);
//                    supplyMarketDO.setStatus(SupplyMarketEnum.UNCHANGED_PRICE.getCode());
//                } else {
//                    BigDecimal bigDecimal = supplyMarketDOS.get(0).getAveragePrice();
//                    if (averagePrice.compareTo(bigDecimal) > 0) {
//                        //涨价
//                        supplyMarketDO.setStatus(SupplyMarketEnum.RISE_IN_PRICE.getCode());
//                        supplyMarketDO.setSalePrice(averagePrice.subtract(bigDecimal));
//                    }
//                    if (averagePrice.compareTo(bigDecimal) == 0) {
//                        //未涨
//                        supplyMarketDO.setSalePrice(BigDecimal.ZERO);
//                        supplyMarketDO.setStatus(SupplyMarketEnum.UNCHANGED_PRICE.getCode());
//                    }
//                    if (averagePrice.compareTo(bigDecimal) < 0) {
//                        //降价
//                        supplyMarketDO.setStatus(SupplyMarketEnum.DEPRECIATE.getCode());
//                        supplyMarketDO.setSalePrice(bigDecimal.subtract(averagePrice));
//                    }
//                }

    }
}

@Data
@AllArgsConstructor
class Key {
    Integer a;
    Integer b;
    Integer c;
    Integer d;
}
